import * as THREE from 'three'

function toMaterial(source) {

  this.name = source.name

  this.fog = source.fog

  this.blending = source.blending
  this.side = source.side
  this.vertexColors = source.vertexColors

  this.opacity = source.opacity
  this.transparent = source.transparent

  this.blendSrc = source.blendSrc
  this.blendDst = source.blendDst
  this.blendEquation = source.blendEquation
  this.blendSrcAlpha = source.blendSrcAlpha
  this.blendDstAlpha = source.blendDstAlpha
  this.blendEquationAlpha = source.blendEquationAlpha

  this.depthFunc = source.depthFunc
  this.depthTest = source.depthTest
  this.depthWrite = source.depthWrite

  this.stencilWriteMask = source.stencilWriteMask
  this.stencilFunc = source.stencilFunc
  this.stencilRef = source.stencilRef
  this.stencilFuncMask = source.stencilFuncMask
  this.stencilFail = source.stencilFail
  this.stencilZFail = source.stencilZFail
  this.stencilZPass = source.stencilZPass
  this.stencilWrite = source.stencilWrite

  const srcPlanes = source.clippingPlanes
  let dstPlanes = null

  if (srcPlanes !== null) {

    const n = srcPlanes.length
    dstPlanes = new Array(n)

    for (let i = 0; i !== n; ++i) {

      dstPlanes[i] = srcPlanes[i].clone()

    }

  }

  this.clippingPlanes = dstPlanes
  this.clipIntersection = source.clipIntersection
  this.clipShadows = source.clipShadows

  this.shadowSide = source.shadowSide

  this.colorWrite = source.colorWrite

  this.precision = source.precision

  this.polygonOffset = source.polygonOffset
  this.polygonOffsetFactor = source.polygonOffsetFactor
  this.polygonOffsetUnits = source.polygonOffsetUnits

  this.dithering = source.dithering

  this.alphaTest = source.alphaTest
  this.alphaToCoverage = source.alphaToCoverage
  this.premultipliedAlpha = source.premultipliedAlpha

  this.visible = source.visible

  this.toneMapped = source.toneMapped

  this.userData = JSON.parse(JSON.stringify(source.userData))

}

export function toMeshBasicMaterial(source) {
  const meshBasicMaterial = new THREE.MeshBasicMaterial()
  toMaterial.call(meshBasicMaterial, source)

  if (source.color) meshBasicMaterial.color.copy(source.color)

  if (source.map) meshBasicMaterial.map = source.map

  if (source.lightMap) meshBasicMaterial.lightMap = source.lightMap
  if (source.lightMapIntensity) meshBasicMaterial.lightMapIntensity = source.lightMapIntensity

  if (source.aoMap) meshBasicMaterial.aoMap = source.aoMap
  if (source.aoMapIntensity) meshBasicMaterial.aoMapIntensity = source.aoMapIntensity

  if (source.specularMap) meshBasicMaterial.specularMap = source.specularMap

  if (source.alphaMap) meshBasicMaterial.alphaMap = source.alphaMap

  if (source.envMap) meshBasicMaterial.envMap = source.envMap
  if (source.combine) meshBasicMaterial.combine = source.combine
  if (source.reflectivity) meshBasicMaterial.reflectivity = source.reflectivity
  if (source.refractionRatio) meshBasicMaterial.refractionRatio = source.refractionRatio

  if (source.wireframe) meshBasicMaterial.wireframe = source.wireframe
  if (source.wireframeLinewidth) meshBasicMaterial.wireframeLinewidth = source.wireframeLinewidth
  if (source.wireframeLinecap) meshBasicMaterial.wireframeLinecap = source.wireframeLinecap
  if (source.wireframeLinejoin) meshBasicMaterial.wireframeLinejoin = source.wireframeLinejoin

  if (source.morphTargets) meshBasicMaterial.morphTargets = source.morphTargets

  return meshBasicMaterial
}

export function toMeshLambertMaterial(source) {
  const meshLambertMaterial = new THREE.MeshLambertMaterial()
  toMaterial.call(meshLambertMaterial, source)

  if (source.color) meshLambertMaterial.color.copy(source.color)

  if (source.map) meshLambertMaterial.map = source.map

  if (source.lightMap) meshLambertMaterial.lightMap = source.lightMap
  if (source.lightMapIntensity) meshLambertMaterial.lightMapIntensity = source.lightMapIntensity

  if (source.aoMap) meshLambertMaterial.aoMap = source.aoMap
  if (source.aoMapIntensity) meshLambertMaterial.aoMapIntensity = source.aoMapIntensity

  if (source.emissive) meshLambertMaterial.emissive.copy(source.emissive)
  if (source.emissiveMap) meshLambertMaterial.emissiveMap = source.emissiveMap
  if (source.emissiveIntensity) meshLambertMaterial.emissiveIntensity = source.emissiveIntensity

  if (source.specularMap) meshLambertMaterial.specularMap = source.specularMap

  if (source.alphaMap) meshLambertMaterial.alphaMap = source.alphaMap

  if (source.envMap) meshLambertMaterial.envMap = source.envMap
  if (source.combine) meshLambertMaterial.combine = source.combine
  if (source.reflectivity) meshLambertMaterial.reflectivity = source.reflectivity
  if (source.refractionRatio) meshLambertMaterial.refractionRatio = source.refractionRatio

  if (source.wireframe) meshLambertMaterial.wireframe = source.wireframe
  if (source.wireframeLinewidth) meshLambertMaterial.wireframeLinewidth = source.wireframeLinewidth
  if (source.wireframeLinecap) meshLambertMaterial.wireframeLinecap = source.wireframeLinecap
  if (source.wireframeLinejoin) meshLambertMaterial.wireframeLinejoin = source.wireframeLinejoin

  if (source.morphTargets) meshLambertMaterial.morphTargets = source.morphTargets
  if (source.morphNormals) meshLambertMaterial.morphNormals = source.morphNormals

  return meshLambertMaterial
}

export function toMeshPhongMaterial(source) {
  const meshPhongMaterial = new THREE.MeshPhongMaterial()
  toMaterial.call(meshPhongMaterial, source)

  if (source.color) meshPhongMaterial.color.copy(source.color)
  if (source.specular) meshPhongMaterial.specular.copy(source.specular)
  if (source.shininess) meshPhongMaterial.shininess = source.shininess

  if (source.map) meshPhongMaterial.map = source.map

  if (source.lightMap) meshPhongMaterial.lightMap = source.lightMap
  if (source.lightMapIntensity) meshPhongMaterial.lightMapIntensity = source.lightMapIntensity

  if (source.aoMap) meshPhongMaterial.aoMap = source.aoMap
  if (source.aoMapIntensity) meshPhongMaterial.aoMapIntensity = source.aoMapIntensity

  if (source.emissive) meshPhongMaterial.emissive.copy(source.emissive)
  if (source.emissiveMap) meshPhongMaterial.emissiveMap = source.emissiveMap
  if (source.emissiveIntensity) meshPhongMaterial.emissiveIntensity = source.emissiveIntensity

  if (source.bumpMap) meshPhongMaterial.bumpMap = source.bumpMap
  if (source.bumpScale) meshPhongMaterial.bumpScale = source.bumpScale

  if (source.normalMap) meshPhongMaterial.normalMap = source.normalMap
  if (source.normalMapType) meshPhongMaterial.normalMapType = source.normalMapType
  if (source.normalScale) meshPhongMaterial.normalScale.copy(source.normalScale)

  if (source.displacementMap) meshPhongMaterial.displacementMap = source.displacementMap
  if (source.displacementScale) meshPhongMaterial.displacementScale = source.displacementScale
  if (source.displacementBias) meshPhongMaterial.displacementBias = source.displacementBias

  if (source.specularMap) meshPhongMaterial.specularMap = source.specularMap

  if (source.alphaMap) meshPhongMaterial.alphaMap = source.alphaMap

  if (source.envMap) meshPhongMaterial.envMap = source.envMap
  if (source.combine) meshPhongMaterial.combine = source.combine
  if (source.reflectivity) meshPhongMaterial.reflectivity = source.reflectivity
  if (source.refractionRatio) meshPhongMaterial.refractionRatio = source.refractionRatio

  if (source.wireframe) meshPhongMaterial.wireframe = source.wireframe
  if (source.wireframeLinewidth) meshPhongMaterial.wireframeLinewidth = source.wireframeLinewidth
  if (source.wireframeLinecap) meshPhongMaterial.wireframeLinecap = source.wireframeLinecap
  if (source.wireframeLinejoin) meshPhongMaterial.wireframeLinejoin = source.wireframeLinejoin

  if (source.morphTargets) meshPhongMaterial.morphTargets = source.morphTargets
  if (source.morphNormals) meshPhongMaterial.morphNormals = source.morphNormals

  if (source.flatShading) meshPhongMaterial.flatShading = source.flatShading

  return meshPhongMaterial
}

export function toMeshStandardMaterial(source) {
  const meshStandardMaterial = new THREE.MeshStandardMaterial()
  toMaterial.call(meshStandardMaterial, source)

  if (source.color) meshStandardMaterial.color.copy(source.color)
  if (source.specular && meshStandardMaterial.specular) meshStandardMaterial.specular.copy(source.specular)
  if (source.shininess) meshStandardMaterial.shininess = source.shininess

  if (source.map) meshStandardMaterial.map = source.map

  if (source.lightMap) meshStandardMaterial.lightMap = source.lightMap
  if (source.lightMapIntensity) meshStandardMaterial.lightMapIntensity = source.lightMapIntensity

  if (source.aoMap) meshStandardMaterial.aoMap = source.aoMap
  if (source.aoMapIntensity) meshStandardMaterial.aoMapIntensity = source.aoMapIntensity

  if (source.emissive) meshStandardMaterial.emissive.copy(source.emissive)
  if (source.emissiveMap) meshStandardMaterial.emissiveMap = source.emissiveMap
  if (source.emissiveIntensity) meshStandardMaterial.emissiveIntensity = source.emissiveIntensity

  if (source.bumpMap) meshStandardMaterial.bumpMap = source.bumpMap
  if (source.bumpScale) meshStandardMaterial.bumpScale = source.bumpScale

  if (source.normalMap) meshStandardMaterial.normalMap = source.normalMap
  if (source.normalMapType) meshStandardMaterial.normalMapType = source.normalMapType
  if (source.normalScale) meshStandardMaterial.normalScale.copy(source.normalScale)

  if (source.displacementMap) meshStandardMaterial.displacementMap = source.displacementMap
  if (source.displacementScale) meshStandardMaterial.displacementScale = source.displacementScale
  if (source.displacementBias) meshStandardMaterial.displacementBias = source.displacementBias

  if (source.specularMap) meshStandardMaterial.specularMap = source.specularMap

  if (source.alphaMap) meshStandardMaterial.alphaMap = source.alphaMap

  if (source.envMap) meshStandardMaterial.envMap = source.envMap
  if (source.combine) meshStandardMaterial.combine = source.combine
  if (source.reflectivity) meshStandardMaterial.reflectivity = source.reflectivity
  if (source.refractionRatio) meshStandardMaterial.refractionRatio = source.refractionRatio

  if (source.wireframe) meshStandardMaterial.wireframe = source.wireframe
  if (source.wireframeLinewidth) meshStandardMaterial.wireframeLinewidth = source.wireframeLinewidth
  if (source.wireframeLinecap) meshStandardMaterial.wireframeLinecap = source.wireframeLinecap
  if (source.wireframeLinejoin) meshStandardMaterial.wireframeLinejoin = source.wireframeLinejoin

  if (source.morphTargets) meshStandardMaterial.morphTargets = source.morphTargets
  if (source.morphNormals) meshStandardMaterial.morphNormals = source.morphNormals

  if (source.flatShading) meshStandardMaterial.flatShading = source.flatShading

  return meshStandardMaterial
}

export function toMeshPhysicalMaterial(source) {
  const meshPhysicalMaterial = new THREE.MeshPhysicalMaterial()
  toMaterial.call(meshPhysicalMaterial, source)

  if (source.color) meshPhysicalMaterial.color.copy(source.color)
  if (source.specular && meshPhysicalMaterial.specular) meshPhysicalMaterial.specular.copy(source.specular)
  if (source.shininess) meshPhysicalMaterial.shininess = source.shininess

  if (source.map) meshPhysicalMaterial.map = source.map

  if (source.lightMap) meshPhysicalMaterial.lightMap = source.lightMap
  if (source.lightMapIntensity) meshPhysicalMaterial.lightMapIntensity = source.lightMapIntensity

  if (source.aoMap) meshPhysicalMaterial.aoMap = source.aoMap
  if (source.aoMapIntensity) meshPhysicalMaterial.aoMapIntensity = source.aoMapIntensity

  if (source.emissive) meshPhysicalMaterial.emissive.copy(source.emissive)
  if (source.emissiveMap) meshPhysicalMaterial.emissiveMap = source.emissiveMap
  if (source.emissiveIntensity) meshPhysicalMaterial.emissiveIntensity = source.emissiveIntensity

  if (source.bumpMap) meshPhysicalMaterial.bumpMap = source.bumpMap
  if (source.bumpScale) meshPhysicalMaterial.bumpScale = source.bumpScale

  if (source.normalMap) meshPhysicalMaterial.normalMap = source.normalMap
  if (source.normalMapType) meshPhysicalMaterial.normalMapType = source.normalMapType
  if (source.normalScale) meshPhysicalMaterial.normalScale.copy(source.normalScale)

  if (source.displacementMap) meshPhysicalMaterial.displacementMap = source.displacementMap
  if (source.displacementScale) meshPhysicalMaterial.displacementScale = source.displacementScale
  if (source.displacementBias) meshPhysicalMaterial.displacementBias = source.displacementBias

  if (source.specularMap) meshPhysicalMaterial.specularMap = source.specularMap

  if (source.alphaMap) meshPhysicalMaterial.alphaMap = source.alphaMap

  if (source.envMap) meshPhysicalMaterial.envMap = source.envMap
  if (source.combine) meshPhysicalMaterial.combine = source.combine
  if (source.reflectivity) meshPhysicalMaterial.reflectivity = source.reflectivity
  if (source.refractionRatio) meshPhysicalMaterial.refractionRatio = source.refractionRatio

  if (source.wireframe) meshPhysicalMaterial.wireframe = source.wireframe
  if (source.wireframeLinewidth) meshPhysicalMaterial.wireframeLinewidth = source.wireframeLinewidth
  if (source.wireframeLinecap) meshPhysicalMaterial.wireframeLinecap = source.wireframeLinecap
  if (source.wireframeLinejoin) meshPhysicalMaterial.wireframeLinejoin = source.wireframeLinejoin

  if (source.morphTargets) meshPhysicalMaterial.morphTargets = source.morphTargets
  if (source.morphNormals) meshPhysicalMaterial.morphNormals = source.morphNormals

  if (source.flatShading) meshPhysicalMaterial.flatShading = source.flatShading

  return meshPhysicalMaterial
}

export default {
  toMaterial,
  toMeshBasicMaterial,
  toMeshLambertMaterial,
  toMeshPhongMaterial,
  toMeshStandardMaterial,
  toMeshPhysicalMaterial
}
